package com.hint.aspect;

import lombok.AllArgsConstructor;
import org.apache.shardingsphere.api.hint.HintManager;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * AOP，Hint要每个方法都要配置一下所以最好放到AOP
 * @author hbz
 */
@Aspect
@Component
@AllArgsConstructor
public class HintAspect extends AbstractController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 第一个*代表返回类型不限
     * 第二个*代表所有类
     * 第三个*代表所有方法
     * (..) 代表参数不限
     */
    @Pointcut("execution(* com.hint.controller..*.*(..))")
    public void logPointCut() {
        logger.debug("logPointCut");
    }

    @Before("logPointCut()")
    public void execute(JoinPoint param) {

        // 清除掉历史的规则
        HintManager.clear();
        // Hint分片策略必须要使用 HintManager工具类
        HintManager hintManager = HintManager.getInstance();
        // 设置库的分片健,value用于库分片取模，(这里3L随便写，只要是基数就行，因为要去策略类和2取模，因为2个库，所以和2取模)
        // 库分片这里注意第一个参数，人家给了提示是logicTable，所以用逻辑表作为第一个参数
        hintManager.addDatabaseShardingValue("product_order", 3L);
        // 设置表的分片健,value用于表分片取模，(这里8L随便写，只要是基数就行，因为要去策略类和2取模，因为2个库，所以和2取模)
        hintManager.addTableShardingValue("product_order", 8L);

        // 如果在读写分离数据库中，Hint 可以强制读主库（主从复制存在一定延时，但在业务场景中，可能更需要保证数据的实时性）
        //hintManager.setMasterRouteOnly();
    }

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return null;
    }
}
